home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / PRG / PowerLisp 2.01 FAT Folder.sit / PowerLisp 2.01 FAT Folder / PowerLisp 2.01 ƒ / Library / assembler_ppc.lisp < prev    next >
Lisp/Scheme  |  1996-05-17  |  23KB  |  818 lines

  1. ;;;
  2. ;;;        PowerLisp 2.0
  3. ;;;        Copyright ゥ 1996 Roger Corman.  All rights reserved.
  4. ;;;        PowerPC Assembler source
  5. ;;;
  6.  
  7. ;
  8. ;    Source code for assembler.
  9. ;
  10.  
  11. (eval-when (:compile-toplevel :load-toplevel :execute)
  12.     (provide :assembler)
  13.     (in-package :assembler))
  14.  
  15. (eval-when (:compile-toplevel :load-toplevel :execute)
  16. (export 
  17. '(
  18.     r0  r1  r2  r3  r4  r5  r6  r7
  19.     r8  r9  r10  r11 r12 r13 r14 r15
  20.     r16 r17 r18  r19 r20 r21 r22 r23
  21.     r24 r25 r26  r27 r28 r29 r30 r31 sp rtoc
  22.     fp0  fp1  fp2   fp3  fp4  fp5  fp6  fp7
  23.     fp8  fp9  fp10  fp11 fp12 fp13 fp14 fp15
  24.     fp16 fp17 fp18  fp19 fp20 fp21 fp22 fp23
  25.     fp24 fp25 fp26  fp27 fp28 fp29 fp30 fp31
  26.     registers
  27.     float-registers
  28.     $CAR
  29.     $CDR
  30.     $SETCAR
  31.     $SETCDR
  32.     $SYMBOL-VALUE
  33.     $SYMBOL-PLIST
  34.     $CONSP
  35.     $INTEGER
  36.     $RETURN
  37.     $FUNC-BEGIN
  38.     $IF
  39.     $IFELSE
  40.     $LOAD-OBJ
  41.     $LOAD-LONG
  42.     $CALL
  43.     $REFERENCE
  44.     dc.l
  45.     blr
  46.     b
  47.     bl
  48.     bla
  49.     bc
  50.     bne
  51.     beq
  52.     blt
  53.     mr
  54.     stw
  55.     stwu
  56.     lwz
  57.     lbz
  58.     lbzu
  59.     addi
  60.     addis
  61.     add
  62.     or_
  63.     ori
  64.     oris
  65.     li
  66.     lis
  67.     cmpwi
  68.     cmpw
  69.     mtlr
  70.     mflr
  71.     stmw
  72.     lmw
  73.     lwzu
  74.     sraw
  75.     sraw.
  76.     andi.
  77.     lfd
  78.     mtctr
  79.     bctr
  80.     bctrl
  81. )))
  82.  
  83. (defconstant r0 0)
  84. (defconstant r1 1)
  85. (defconstant r2 2)
  86. (defconstant r3 3)
  87. (defconstant r4 4)
  88. (defconstant r5 5)
  89. (defconstant r6 6)
  90. (defconstant r7 7)
  91. (defconstant r8 8)
  92. (defconstant r9 9)
  93. (defconstant r10 10)
  94. (defconstant r11 11)
  95. (defconstant r12 12)
  96. (defconstant r13 13)
  97. (defconstant r14 14)
  98. (defconstant r15 15)
  99. (defconstant r16 16)
  100. (defconstant r17 17)
  101. (defconstant r18 18)
  102. (defconstant r19 19)
  103. (defconstant r20 20)
  104. (defconstant r21 21)
  105. (defconstant r22 22)
  106. (defconstant r23 23)
  107. (defconstant r24 24)
  108. (defconstant r25 25)
  109. (defconstant r26 26)
  110. (defconstant r27 27)
  111. (defconstant r28 28)
  112. (defconstant r29 29)
  113. (defconstant r30 30)
  114. (defconstant r31 31)
  115.  
  116. (defconstant fp0 0)
  117. (defconstant fp1 1)
  118. (defconstant fp2 2)
  119. (defconstant fp3 3)
  120. (defconstant fp4 4)
  121. (defconstant fp5 5)
  122. (defconstant fp6 6)
  123. (defconstant fp7 7)
  124. (defconstant fp8 8)
  125. (defconstant fp9 9)
  126. (defconstant fp10 10)
  127. (defconstant fp11 11)
  128. (defconstant fp12 12)
  129. (defconstant fp13 13)
  130. (defconstant fp14 14)
  131. (defconstant fp15 15)
  132. (defconstant fp16 16)
  133. (defconstant fp17 17)
  134. (defconstant fp18 18)
  135. (defconstant fp19 19)
  136. (defconstant fp20 20)
  137. (defconstant fp21 21)
  138. (defconstant fp22 22)
  139. (defconstant fp23 23)
  140. (defconstant fp24 24)
  141. (defconstant fp25 25)
  142. (defconstant fp26 26)
  143. (defconstant fp27 27)
  144. (defconstant fp28 28)
  145. (defconstant fp29 29)
  146. (defconstant fp30 30)
  147. (defconstant fp31 31)
  148.  
  149. (defconstant registers 
  150.    '(r0  r1  r2  r3  r4  r5  r6  r7
  151.      r8  r9  r10  r11 r12 r13 r14 r15
  152.      r16 r17 r18  r19 r20 r21 r22 r23
  153.      r24 r25 r26  r27 r28 r29 r30 r31 sp rtoc))
  154.  
  155. (defconstant sp r1)
  156. (defconstant rtoc r2)
  157.  
  158. (defconstant float-registers 
  159.     '(fp0  fp1  fp2   fp3  fp4  fp5  fp6  fp7
  160.       fp8  fp9  fp10  fp11 fp12 fp13 fp14 fp15
  161.       fp16 fp17 fp18  fp19 fp20 fp21 fp22 fp23
  162.       fp24 fp25 fp26  fp27 fp28 fp29 fp30 fp31))
  163.  
  164.  
  165. ;;    Macros to access SYMBOL and NODE fields.
  166. ;;    These are dependent on the symbol class definition.
  167. ;;    The C++ source is in LispObjects.h.
  168.  
  169. (defconstant *symbol-value-offset*                 8)
  170. (defconstant *symbol-plist-offset*                 12)
  171. (defconstant *symbol-package-offset*             16)
  172. (defconstant *symbol-name-offset*                 20)
  173. (defconstant *symbol-flags-offset*                 24)
  174. (defconstant *symbol-jump-table-entry-offset*     26)
  175. (defconstant *symbol-jump-address-offset*         28)
  176. (defconstant *symbol-function-offset*             32)
  177.  
  178. (defconstant *node-car-offset*                    0)
  179. (defconstant *node-cdr-offset*                    4)
  180. (defconstant *node-flags-offset*                8)
  181. (defconstant *node-type-offset*                    9)
  182.  
  183. (defvar *assembler-address*    0)
  184. (defvar *assembler-references*    nil)
  185.  
  186. ;
  187. ;    We do an eval-when on the entire file so that we get the
  188. ;    performance benefits immediately
  189. ;
  190. (eval-when (:compile-toplevel :load-toplevel :execute)
  191.  
  192. (defmacro $CAR (node &optional dest-reg)
  193.     (unless dest-reg (setq dest-reg node))
  194.     `(
  195.         (lwz ,dest-reg (,node ,*node-car-offset*))
  196.      )) 
  197.  
  198. (defmacro $CDR (node &optional dest-reg)
  199.     (unless dest-reg (setq dest-reg node))
  200.     `(
  201.         (lwz ,dest-reg (,node ,*node-cdr-offset*))
  202.      )) 
  203.  
  204. (defmacro $SETCAR (node value)
  205.     `(
  206.         (stw ,value (,node ,*node-car-offset*))
  207.      )) 
  208.  
  209. (defmacro $SETCDR (node value)
  210.     `(
  211.         (stw ,value (,node ,*node-cdr-offset*))
  212.      )) 
  213.  
  214. (defmacro $SYMBOL-VALUE (node)
  215.     `(
  216.         (lwz ,node (,node))        ;; get symbol object
  217.         (lwz ,node (,node ,*symbol-value-offset*))    ;; get value cons
  218.         (lwz ,node (,node))        ;; value in car field
  219.      )) 
  220.  
  221. (defmacro $SYMBOL-PLIST (node)
  222.     `(
  223.         (lwz ,node (,node))        ;; get symbol object
  224.         (lwz ,node (,node ,*symbol-plist-offset*))
  225.      )) 
  226.  
  227. (defmacro $CONSP (node)
  228.     `(
  229.         ($IF
  230.         ((andi. r0 ,node 1))        ; (if (not (integerp node)) ...
  231.         ((lbz ,node (,node ,*node-type-offset*))
  232.         (cmpwi r0 0)))
  233.     ))
  234.  
  235. (defmacro $INTEGER (node &optional dest-reg)
  236.     (unless dest-reg (setq dest-reg node))
  237.     `(
  238.         (sraw ,node ,node 1)        ;; shift right one bit to find integer
  239.      )) 
  240.  
  241.     
  242. ;;
  243. ;;    The $RETURN macro zeros out the multiple value cell, stores
  244. ;;    the passed value in r3 (to return it), and unlinks the stack frame.
  245. ;;
  246. (defmacro $RETURN (retval stacksize)
  247.     (if (eq retval 'r3)
  248.         `(
  249.             ($LOAD-LONG r5 cl::%multiple-values-address)
  250.             (li r4 0)
  251.             (stw r4 (r5))
  252.             (addi sp sp ,stacksize)
  253.             (lwz r0 (sp 8))
  254.             (mtlr r0)
  255.             (blr)
  256.          ) 
  257.         `(
  258.             (mr r3 ,retval)
  259.             ($LOAD-LONG r5 cl::%multiple-values-address)
  260.             (li r4 0)
  261.             (stw r4 (r5))
  262.             (addi sp sp ,stacksize)
  263.             (lwz r0 (sp 8))
  264.             (mtlr r0)
  265.             (blr)
  266.          ))) 
  267.  
  268. ;;
  269. ;;    The $FUNC-BEGIN macro sets up the A6 stack frame link,
  270. ;;    and stores a pointer to the parameter block in A0.
  271. ;;    Usage:
  272. ;;        ($FUNC-BEGIN 4)        ;; allocates 4 bytes (space for one object)
  273. ;;                            ;; on the stack
  274. ;;
  275. (defmacro $FUNC-BEGIN (size)
  276.     `(
  277.         (mflr r0)
  278.         (stw r0 (sp 8))
  279. ;        (lwz rtoc (sp 20))    ;; don't need this anymore
  280.         (stwu sp (sp ,(- size)))
  281.      )) 
  282.  
  283. ;;
  284. ;;    $IF macro
  285. ;;    Usage:
  286. ;;        ($IF    
  287. ;;            (cmpwi r7 0)         ;; if r7 == 0 the next statement will be executed
  288. ;;            (
  289. ;;                (mr r0 r3)
  290. ;;            ))
  291. ;;
  292. (defmacro $IF (condition instructions)
  293.     (let ((temp-label (gensym)))
  294.         ;;    allow single instruction clauses or lists of instructions
  295.         (if (not (listp (car condition)))
  296.             (setq condition (list condition)))
  297.         (if (not (listp (car instructions)))
  298.             (setq instructions (list instructions)))
  299.  
  300.         `(
  301.             ,@condition
  302.             (bne ,temp-label)
  303.             ,@instructions
  304.             ,temp-label
  305.          ))) 
  306.  
  307. ;;
  308. ;;    $IFELSE macro
  309. ;;    Usage:
  310. ;;        ($IFELSE    
  311. ;;            (cmpwi r7 0)         ;; if r7 == 0 the next instruction will be executed
  312. ;;            (
  313. ;;                (mr r0 r3)
  314. ;;            )
  315. ;;            (
  316. ;;                (mr r2 r3)    ;; otherwise this instruction will be executed
  317. ;;            ))
  318. ;;
  319. (defmacro $IFELSE (condition if-instructions else-instructions)
  320.     (let ((else-label (gensym)) 
  321.           (exit-label (gensym)))
  322.  
  323.         ;;    allow single instruction clauses or lists of instructions
  324.         (if (not (listp (car condition)))
  325.             (setq condition (list condition)))
  326.         (if (not (listp (car if-instructions)))
  327.             (setq if-instructions (list if-instructions)))
  328.         (if (not (listp (car else-instructions)))
  329.             (setq else-instructions (list else-instructions)))
  330.         
  331.         `(
  332.             ,@condition
  333.             (bne ,else-label)
  334.             ,@if-instructions
  335.             (b ,exit-label)
  336.             ,else-label
  337.             ,@else-instructions
  338.             ,exit-label
  339.          ))) 
  340.  
  341. (defmacro $LOAD-OBJ (reg obj)
  342.     (let ((exec (eval obj)))
  343.         (add-reference obj)
  344.         `((lis ,reg ,(ash (address exec) -16))
  345.           (ori ,reg ,reg ,(mod (address exec) #x10000)))))
  346.  
  347. (defmacro $LOAD-LONG (reg n)
  348.     (if (symbolp n)
  349.         (progn
  350.             (add-reference `(symbol-value ,n))
  351.             (setq n (symbol-value n))))
  352.     `((lis ,reg ,(ash n -16))
  353.       (ori ,reg ,reg ,(mod n #x10000))))
  354.  
  355. (defmacro $CALL (func)
  356. ;;    `((bla ,func))
  357.     (if (or (not (consp func)) 
  358.             (not (consp (cdr func))) 
  359.             (not (eq (car func) 'function)))
  360.         (error "Invalid call form: ~A" func))
  361.     
  362.     (add-reference func)
  363.     (let ((xaddr (exec-address (cadr func))))
  364.  
  365.         `((lis r26 ,(cl::%fixnum-upper16 xaddr))
  366.             (ori r26 r26 ,(cl::%fixnum-lower16 xaddr))
  367.           (mtctr r26)
  368.           (bctrl))))
  369.  
  370. ;;
  371. ;;    The $REFERENCE macro does not generate any instructions, but
  372. ;;    is used by the compiler as a flag to the assembler to correctly
  373. ;;    generate address reference entries when code is compiled to a file.
  374. ;;
  375. (defmacro $REFERENCE (referenced-item)
  376.     nil)
  377.  
  378. (defun check-source-reg-or-0 (source)
  379.     (if (not (or (member source registers) (zerop source)))
  380.         (error "Invalid source. source: ~A" source))
  381.     (if (not (and (integerp source) (zerop source))) (symbol-value source) source))
  382.  
  383. (defun check-source-reg (source)
  384.     (if (not (member source registers))
  385.         (error "Invalid source. source: ~A" source))
  386.     (symbol-value source))
  387.  
  388. (defun check-reg (r)
  389.     (if (not (member r registers))
  390.         (error "Invalid register. register: ~A" r))
  391.     (symbol-value r))
  392.  
  393. (defun check-float-reg (r)
  394.     (if (not (member r float-registers))
  395.         (error "Invalid floating point register. register: ~A" r))
  396.     (symbol-value r))
  397.  
  398. (defun check-dest-reg-or-0 (dest)
  399.     (if (not (or (member dest registers) (zerop dest)))
  400.         (error "Invalid destination. destination: ~A" dest))
  401.     (if (symbolp dest) (symbol-value dest) dest))
  402.  
  403. (defun check-dest-reg (dest)
  404.     (if (not (member dest registers))
  405.         (error "Invalid destination. destination: ~A" dest))
  406.     (symbol-value dest))
  407.  
  408. (defun format-sreg-dreg-u16 (instruction code sreg dreg uimm)
  409.     (setq sreg (check-source-reg sreg))
  410.     (setq dreg (check-dest-reg dreg))
  411.     (if (> (integer-length uimm) 16)
  412.         (error "Displacement too large.~%Instruction: ~A  Displacement: ~A" 
  413.                 instruction uimm))
  414.     (+ (ash code 26) (ash sreg 21) (ash dreg 16) (logand uimm #xffff)))
  415.  
  416. (defun format-sreg-dreg-sreg (instruction code s1 d s2 scode)    
  417.     (setq s1 (check-source-reg s1))
  418.     (setq d (check-dest-reg d))
  419.     (setq s2 (check-source-reg s2))
  420.     (+ (ash code 26) (ash s1 21) (ash d 16) (ash s2 11) scode))
  421.             
  422. (defun format-sreg-dreg-imm (instruction code s d imm scode)    
  423.     (setq s (check-source-reg s))
  424.     (setq d (check-dest-reg d))
  425.     (+ (ash code 26) (ash s 21) (ash d 16) (ash imm 11) scode))
  426.  
  427. (defun format-fdreg-sreg-disp (instruction code fdreg sreg disp)
  428.     (setq fdreg (check-float-reg fdreg))
  429.     (setq sreg (check-source-reg sreg))
  430.     (if (> (integer-length disp) 16)
  431.         (error "Displacement too large.~%Instruction: ~A  Displacement: ~A" 
  432.                 instruction disp))
  433.     (+ (ash code 26) (ash fdreg 21) (ash sreg 16) (logand disp #xffff)))
  434.  
  435.             
  436. (defmacro dc.l (w) 
  437.     (cond 
  438.         ((symbolp w) 
  439.          (add-reference `(symbol-value ,w))
  440.          (list (symbol-value w)))
  441.         (t (list w))))
  442.  
  443. (defmacro blr ()   (list #x4E800020))
  444. (defmacro bctr ()  (list #x4E800420))
  445. (defmacro bctrl () (list #x4E800421))
  446.  
  447. (defmacro b (dst)
  448.     (if (symbolp dst) 
  449.         (return (list (ash 18 26) dst)))
  450.     (if (consp dst)
  451.         (if (eq (car dst) 'function)
  452.             (let ((instruction 0)
  453.                   (addr (exec-address (cadr dst))))
  454.                 (add-reference dst)
  455.                 (setq instruction (+ (ash 18 26) addr))
  456.                 (return (list instruction)))
  457.         ;; else
  458.             (error "Invalid destination.~%Instruction: bla  Destination: ~A" dst)))        
  459.     (let ((instruction 0))
  460.         (add-reference dst)
  461.         (setq instruction (+ (ash 18 26) dst))
  462.         (list instruction)))
  463.  
  464. (defmacro bl (dst)
  465.     (if (symbolp dst) 
  466.         (return (list (+ (ash 18 26) 1) dst)))
  467.     (if (consp dst)
  468.         (if (eq (car dst) 'function)
  469.             (let ((instruction 0)
  470.                   (addr (exec-address (cadr dst))))
  471.                 (add-reference dst)
  472.                 (setq instruction (+ (ash 18 26) addr 1))
  473.                 (return (list instruction)))
  474.         ;; else
  475.             (error "Invalid destination.~%Instruction: bla  Destination: ~A" dst)))        
  476.     (let ((instruction 0))
  477. ;        (add-reference dst)
  478.         (setq instruction (+ (ash 18 26) dst 1))
  479.         (list instruction)))
  480.  
  481. (defmacro bc (bo bi dst)
  482.     (if (symbolp dst) 
  483.         (return 
  484.             (list (+ (ash 16 26) (ash bo 21) (ash bi 16)) dst)))
  485.     (if (consp dst)
  486.         (if (eq (car dst) 'function)
  487.             (let ((instruction 0)
  488.                   (addr (exec-address (cadr dst))))
  489.                 (add-reference dst)
  490.                 (setq instruction 
  491.                     (+ (ash 16 26) (ash bo 21) (ash bi 16) addr))
  492.                 (return (list instruction)))
  493.         ;; else
  494.             (error "Invalid destination.~%Instruction: bla  Destination: ~A" dst)))        
  495.     (let ((instruction 0))
  496.         (add-reference dst)
  497.         (setq instruction 
  498.             (+ (ash 16 26) (ash bo 21) (ash bi 16) dst))
  499.         (list instruction)))
  500.  
  501. (defmacro bne (dst) `((bc  4 2 ,dst))) 
  502. (defmacro blt (dst) `((bc 12 0 ,dst))) 
  503. (defmacro beq (dst) `((bc 12 2 ,dst))) 
  504.  
  505. (defmacro bla (dst)
  506.     (if (symbolp dst) 
  507.         (progn
  508.             (add-reference `(symbol-value ,dst))
  509.             (setq dst (symbol-value dst))))            
  510.     (if (consp dst)
  511.         (if (eq (car dst) 'function)
  512.             (let ((instruction 0)
  513.                   (addr (exec-address (cadr dst))))
  514.                 (add-reference dst)
  515.                 (setq addr (logior addr 3))        ; set lower 2 bits
  516.                 (setq instruction (+ (ash 18 26) addr))
  517.                 (return (list instruction)))
  518.         ;; else
  519.             (error "Invalid destination.~%Instruction: bla  Destination: ~A" dst)))        
  520.     (let ((instruction 0))
  521.         (add-reference dst)
  522.         (setq instruction (+ (ash 18 26) dst))
  523.         (setq instruction (logior instruction 3))    ; set lower 2 bits
  524.         (list instruction)))
  525.  
  526. (defmacro mr (dst src) `((or_ ,dst ,src ,src))) 
  527.  
  528. (defmacro stw (src dst)
  529.     (if (not (consp dst))
  530.         (error "Invalid destination.~%Instruction: stw  Destination: ~A" dst))        
  531.     (let ((displacement (if (cdr dst) (cadr dst) 0))
  532.           (dest-value (check-dest-reg-or-0 (car dst))))
  533.         (if (> (integer-length displacement) 15)
  534.             (error "Displacement too large.~%Instruction: stw  Displacement: ~A" displacement))            
  535.         (list (+ (ash 36 26) 
  536.                 (ash (symbol-value src) 21) 
  537.                 (ash dest-value 16) 
  538.                 (logand displacement #xffff)))))
  539.  
  540. (defmacro stmw (src dst)
  541.     (if (not (consp dst))
  542.         (error "Invalid destination.~%Instruction: stmw  Destination: ~A" dst))        
  543.     (let ((displacement (if (cdr dst) (cadr dst) 0))
  544.           (dest-value (check-dest-reg-or-0 (car dst))))
  545.         (if (> (integer-length displacement) 15)
  546.             (error "Displacement too large.~%Instruction: stmw  Displacement: ~A" displacement))            
  547.         (list (+ (ash 47 26) 
  548.                 (ash (symbol-value src) 21) 
  549.                 (ash dest-value 16) 
  550.                 (logand displacement #xffff)))))
  551.  
  552. (defmacro stwu (src dst)
  553.     (if (not (consp dst))
  554.         (error "Invalid destination.~%Instruction: stwu  Destination: ~A" dst))        
  555.     (let ((displacement (if (cdr dst) (cadr dst) 0)))
  556.         (if (> (integer-length displacement) 15)
  557.             (error "Displacement too large.~%Instruction: stwu  Displacement: ~A" displacement))            
  558.         (list (+ (ash 37 26) 
  559.                 (ash (symbol-value src) 21) 
  560.                 (ash (symbol-value (car dst)) 16) 
  561.                 (logand displacement #xffff)))))
  562.  
  563. (defmacro lwz (dst src)
  564.     (if (not (consp src))
  565.         (error "Invalid source.~%Instruction: lwz  Source: ~A" src))        
  566.     (let ((displacement (if (cdr src) (cadr src) 0))
  567.           (source (car src)))
  568.         (if (> (integer-length displacement) 15)
  569.             (error "Displacement too large.~%Instruction: lwz  Displacement: ~A" displacement))            
  570.         (setq source (check-source-reg-or-0 source))
  571.         (list (+ (ash 32 26) 
  572.                 (ash (symbol-value dst) 21) 
  573.                 (ash source 16) 
  574.                 (logand displacement #xffff)))))
  575.     
  576. (defmacro lmw (dst src)
  577.     (if (not (consp src))
  578.         (error "Invalid source.~%Instruction: lmw  Source: ~A" src))        
  579.     (let ((displacement (if (cdr src) (cadr src) 0))
  580.           (source (car src)))
  581.         (if (> (integer-length displacement) 15)
  582.             (error "Displacement too large.~%Instruction: lmw  Displacement: ~A" displacement))            
  583.         (setq source (check-source-reg-or-0 source))
  584.         (list (+ (ash 46 26) 
  585.                 (ash (symbol-value dst) 21) 
  586.                 (ash source 16) 
  587.                 (logand displacement #xffff)))))
  588.     
  589. (defmacro lwzu (dst src)
  590.     (if (not (consp src))
  591.         (error "Invalid source.~%Instruction: lwzu  Source: ~A" src))        
  592.     (let ((displacement (if (cdr src) (cadr src) 0))
  593.           (source (car src)))
  594.         (if (> (integer-length displacement) 15)
  595.             (error "Displacement too large.~%Instruction: lwzu  Displacement: ~A" displacement))            
  596.         (setq source (check-source-reg-or-0 source))
  597.         (if (zerop source)
  598.             (error "Source cannot be zero for this instruction~%Instruction: lwzu  Source: ~A" src))
  599.         (list (+ (ash 33 26) 
  600.                 (ash (symbol-value dst) 21) 
  601.                 (ash source 16) 
  602.                 (logand displacement #xffff)))))
  603.     
  604. (defmacro lbz (dst src)
  605.     (if (not (consp src))
  606.         (error "Invalid source.~%Instruction: lbz  Destination: ~A" src))        
  607.     (let ((displacement (if (cdr src) (cadr src) 0))
  608.             (source (car src)))
  609.         (if (> (integer-length displacement) 15)
  610.             (error "Displacement too large.~%Instruction: lwz  Displacement: ~A" displacement))            
  611.         (setq source (check-source-reg-or-0 source))
  612.         (list (+ (ash 34 26) 
  613.                 (ash (symbol-value dst) 21) 
  614.                 (ash source 16) 
  615.                 (logand displacement #xffff)))))
  616.     
  617. (defmacro lbzu (dst src)
  618.     (if (not (consp src))
  619.         (error "Invalid source.~%Instruction: lbzu  Destination: ~A" src))        
  620.     (let ((displacement (if (cdr src) (cadr src) 0))
  621.             (source (car src)))
  622.         (if (> (integer-length displacement) 15)
  623.             (error "Displacement too large.~%Instruction: lwz  Displacement: ~A" displacement))            
  624.         (setq source (check-source-reg-or-0 source))
  625.         (list (+ (ash 35 26) 
  626.                 (ash (symbol-value dst) 21) 
  627.                 (ash source 16) 
  628.                 (logand displacement #xffff)))))
  629.     
  630. (defmacro addi (dst src disp)
  631.     (if (> (integer-length disp) 16)
  632.         (error "Displacement too large.~%Instruction: addi  Displacement: ~A" disp))            
  633.     (setq src (check-source-reg-or-0 src))
  634.     (list (+ (ash 14 26) 
  635.             (ash (symbol-value dst) 21) 
  636.             (ash src 16) 
  637.             (logand disp #xffff))))
  638.  
  639. (defmacro add (dst src1 src2)
  640.     (list (+ (ash 31 26) 
  641.             (ash (symbol-value dst) 21) 
  642.             (ash (symbol-value src1) 16) 
  643.             (ash (symbol-value src2) 11) 
  644.             (ash 266 1))))
  645.  
  646. (defmacro addis (dst src disp)
  647.     (if (> (integer-length disp) 16)
  648.         (error "Displacement too large.~%Instruction: addis  Displacement: ~A" disp))            
  649.     (setq src (check-source-reg-or-0 src))
  650.     (list (+ (ash 15 26) 
  651.             (ash (symbol-value dst) 21) 
  652.             (ash src 16) 
  653.             (logand disp #xffff))))
  654.  
  655. (defmacro or_ (dst src1 src2) (list (format-sreg-dreg-sreg 'or_ 31 src1 dst src2 888)))
  656. (defmacro or. (dst src1 src2) (list (format-sreg-dreg-sreg 'or. 31 src1 dst src2 889)))
  657. (defmacro ori (dst src uimm) (list (format-sreg-dreg-u16 'ori 24 src dst uimm)))
  658. (defmacro oris (dst src uimm) (list (format-sreg-dreg-u16 'oris 25 src dst uimm)))
  659. (defmacro li  (dst disp) `((addi  ,dst 0 ,disp)))
  660. (defmacro lis (dst disp) `((addis ,dst 0 ,disp)))
  661. (defmacro sraw (dst src shift) (list (format-sreg-dreg-imm 'sraw 31 src dst shift 1584)))
  662. (defmacro sraw. (dst src shift) (list (format-sreg-dreg-imm 'sraw. 31 src dst shift 1585)))
  663. (defmacro andi. (dest src uimm) (list (format-sreg-dreg-u16 'andi 28 src dest uimm)))
  664.  
  665. (defmacro lfd (fdest src) 
  666.     (if (not (consp src))
  667.         (error "Invalid source.~%Instruction: lfd  Destination: ~A" src))    
  668.     (let ((disp (if (cdr src) (cadr src) 0))
  669.             (source (car src)))
  670.         (list (format-fdreg-sreg-disp 'lfd 50 fdest source disp))))
  671.  
  672. (defmacro cmpwi (dst simm)
  673.     (if (> (integer-length simm) 15)
  674.         (error "Immediate value too large.~%Instruction: addi  Immediate: ~A" simm))            
  675.     (list (+ (ash 11 26) (ash (symbol-value dst) 16) (logand simm #xffff))))     
  676.  
  677. (defmacro cmpw (a b)
  678.     (setq a (check-reg a))
  679.     (setq b (check-reg b))
  680.     (list (+ (ash 31 26) (ash a 16) (ash b 11))))     
  681.  
  682. (defmacro mtlr (src)
  683.         (list (+ (ash 31 26) (ash (symbol-value src) 21) (ash 8 16) (ash 467 1)))) 
  684.  
  685. (defmacro mflr (dst)
  686.         (list (+ (ash 31 26) (ash (symbol-value dst) 21) (ash 8 16) (ash 339 1)))) 
  687.  
  688. (defmacro mtctr (src)
  689.         (list (+ (ash 31 26) (ash (symbol-value src) 21) (ash 9 16) (ash 467 1)))) 
  690.  
  691. (defun is-relative-branch-instruction (inst)
  692.     (let ((op (ash inst -26)))
  693.         (or (= op 16) (= op 18))))
  694. (defun merge-address (inst offset)
  695.     (let ((op (ash inst -26)))
  696.         (if (= op 16)            ;; 16-bit offset
  697.             (+ inst (logand offset #xfffc))
  698.             (+ inst (logand offset #x3fffffc)))))
  699.             
  700. (defun assemble (assembler-instructions references &optional environment)
  701.   (let*
  702.     ((label-table (make-hash-table :test #'eql))
  703.       (newlist nil)
  704.       (codelist nil)
  705.       (*assembler-address* 0)
  706.       (*assembler-references* nil)
  707.       operator)
  708.  
  709.     (do ((n assembler-instructions (cdr n))
  710.          statement)
  711.         ((null n))
  712.         (setq statement (car n))
  713.         (cond
  714.             ;; if it is a label, add it to the hash table
  715.             ((symbolp statement) 
  716.              (setf (gethash statement label-table) *assembler-address*))
  717.             ((consp statement)
  718.              (if (integerp (car statement))     ;; skip address if there is one
  719.                  (setq statement (cdr statement)))
  720.              
  721.              ;; make sure there is a macro definition
  722.              (setq operator (car statement))
  723.              (unless (symbolp operator) 
  724.                  (error "Invalid instruction: ~A" operator))
  725.              (unless (macro-function operator)
  726.                  (error "No definition for instruction: ~A" statement))
  727.  
  728.              ;; expand the macro one time
  729.              (setq statement (macroexpand-1 statement))
  730.              
  731.              ;; check for multiple statement result (assembler macro expansion)
  732.              (if (and (consp statement) (not (integerp (car statement))))
  733.                  ;; just splice in the new instructions and continue
  734.                 (setq n (append (list nil) statement (cdr n)))
  735.                 (if (consp statement)
  736.                     (progn
  737.                         (incf *assembler-address* 4)
  738.                         (push statement newlist)))))
  739.             
  740.             ;; error if not a symbol or a list
  741.             (t (error "Invalid label encountered: ~A" statement))))
  742.             
  743.     ;; Now go through and append all the sublists together,
  744.     ;; resolving branch addresses as we go.
  745.     ;; We only currently support 16-bit displacements in the branch
  746.     ;; instructions.
  747.  
  748.     (setq newlist (reverse newlist))
  749.     (setq *assembler-address* 0)
  750.  
  751.     (dolist (statement newlist)
  752.         ;; check for branch instructions
  753.         (setq operator (car statement))
  754.         (if (is-relative-branch-instruction operator)
  755.             (if (and (consp (cdr statement))
  756.                     (symbolp (cadr statement)))
  757.                 (let* ((sym (cadr statement))
  758.                         (value (gethash sym label-table)))
  759.                     (unless value 
  760.                         (error "Label not found: ~A" sym))
  761.                     (unless (integerp value) 
  762.                         (error "Invalid label found.~%Label: ~A Value: ~A" sym value))
  763.                     (setf statement 
  764.                         (list (merge-address (car statement) (- value *assembler-address*)))))))
  765.  
  766.         (incf *assembler-address* 4)
  767.         (if statement (push (car statement) codelist)))
  768.  
  769.     (setq newlist nil)
  770.     (dolist (n codelist)
  771.         (push (mod n #x10000) newlist)        
  772.         (push  (ash n -16) newlist))        
  773. ;;    (let ((*print-base* 16)) (format t "newlist = ~A~%" newlist))
  774.     (%build-function newlist (nreverse *assembler-references*) environment)))
  775.  
  776. (defun add-reference (ref &optional (offset 0))
  777.     (push 
  778.         (cons ref (+ *assembler-address* offset)) 
  779.         *assembler-references*))
  780.  
  781. )  ;; close enclosing eval-when form
  782.     
  783. ;;    add defasm to the common lisp package
  784.  
  785. (eval-when (:compile-toplevel :load-toplevel :execute)
  786.     (in-package :common-lisp)
  787.     (export 'common-lisp::defasm))
  788.  
  789. (eval-when (:compile-toplevel :load-toplevel :execute)
  790. (defmacro defasm (name lambda-list &rest forms)
  791. ;    (declare (unused lambda-list))
  792.     (let ((doc-form nil))
  793.         (if (and (typep (car forms) 'string)
  794.                 (cdr forms))
  795.             (progn
  796.                 (setq doc-form 
  797.                     `((setf (documentation ',name 'function) ,(car forms))))
  798.                 (setq forms (cdr forms))))
  799.  
  800.         `(progn
  801.             ,@doc-form
  802.             (setf (symbol-function ',name) ,(car forms))
  803.             (null-environment (function ,name))
  804.             ',name))) 
  805.  
  806. ) ;; close eval-when
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.